Skip to main content

Overview

The Transfers class provides comprehensive access to player transfer data for professional football teams across Europe’s top 5 leagues. It enables tracking both incoming and outgoing transfers for any team in a given season.
Transfer data includes player names, positions, dates, and the clubs involved in each transfer, supporting seasons from the 1920s-1960s onwards depending on the league.

Installation

from premier_league import Transfers

Initialization

transfers = Transfers(
    target_season="2023-2024",
    league="Premier League",
    cache=True
)

Parameters

target_season
str
default:"None"
Specific season in format “YYYY-YYYY” (e.g., “2023-2024”). If None, uses current season
league
str
default:"premier league"
League to scrape transfer data for. Options:
  • “Premier League” (England)
  • “La Liga” (Spain)
  • “Serie A” (Italy)
  • “Bundesliga” (Germany)
  • “Ligue 1” (France)
cache
bool
default:"True"
Whether to cache scraped data for faster subsequent access

Quick Start

from premier_league import Transfers

# Get current season transfers
transfers = Transfers(league="Premier League")

# Print transfer table for a team
transfers.print_transfer_table("Chelsea")

Core Methods

Print formatted transfer tables (both incoming and outgoing) for a specified team.
transfers = Transfers(
    league="Premier League",
    target_season="2023-2024"
)

transfers.print_transfer_table("Arsenal")
Output:
Arsenal >> Transfers 2023-2024 In:
+--------+------------------+----------+----------------------+
| Date   | Name             | Position | Club                 |
+--------+------------------+----------+----------------------+
| 07/01  | Declan Rice      | MF       | West Ham United      |
| 07/15  | Kai Havertz       | FW       | Chelsea              |
+--------+------------------+----------+----------------------+

Arsenal >> Transfers 2023-2024 Out:
+--------+------------------+----------+----------------------+
| Date   | Name             | Position | Club                 |
+--------+------------------+----------+----------------------+
| 06/30  | Granit Xhaka     | MF       | Bayer Leverkusen     |
+--------+------------------+----------+----------------------+

Parameters

team
str
required
Name of the team (fuzzy matching supported)

Raises

TeamNotFoundError: If the specified team is not found in the current season

transfer_in_table()

Get incoming transfers for a specific team as a structured list.
transfers = Transfers(league="Bundesliga")

incoming = transfers.transfer_in_table("Bayern Munich")

# First row is headers
headers = incoming[0]
print(headers)  # ['Date', 'Name', 'Position', 'Club']

# Process each transfer
for transfer in incoming[1:]:
    date, player_name, position, from_club = transfer
    print(f"{player_name} joined from {from_club}")

Parameters

team
str
required
Name of the team

Returns

List[List[str]]: Nested list where:
  • First row: ['Date', 'Name', 'Position', 'Club']
  • Subsequent rows: Individual transfer data

Column Structure

  • Date: Transfer date in MM/DD format
  • Name: Player name
  • Position: Player position (FW, MF, DF, GK)
  • Club: Previous club the player joined from

Raises

TeamNotFoundError: If the team is not found

transfer_out_table()

Get outgoing transfers for a specific team as a structured list.
transfers = Transfers(
    league="Ligue 1",
    target_season="2022-2023"
)

outgoing = transfers.transfer_out_table("PSG")

print("Players who left PSG:")
for transfer in outgoing[1:]:
    date, player_name, position, to_club = transfer
    print(f"{player_name} ({position}) → {to_club}")

Parameters

team
str
required
Name of the team

Returns

List[List[str]]: Nested list with same structure as transfer_in_table()

Column Structure

  • Date: Transfer date in MM/DD format
  • Name: Player name
  • Position: Player position
  • Club: New club the player transferred to

Raises

TeamNotFoundError: If the team is not found

transfer_csv()

Export transfer data to a CSV file.
transfers = Transfers(league="Serie A")

# Export both transfers in and out
transfers.transfer_csv(
    team="Juventus",
    file_name="juventus_transfers",
    transfer_type="both"
)

# Export only incoming transfers
transfers.transfer_csv(
    team="Inter Milan",
    file_name="inter_incoming",
    transfer_type="in"
)

# Export only outgoing transfers
transfers.transfer_csv(
    team="AC Milan",
    file_name="milan_outgoing",
    transfer_type="out"
)

Parameters

team
str
required
Name of the team
file_name
str
required
Name of the CSV file (without .csv extension)
transfer_type
Literal['in', 'out', 'both']
default:"both"
Type of transfers to export:
  • "in": Only incoming transfers
  • "out": Only outgoing transfers
  • "both": Both incoming and outgoing (creates separate sections)

Raises

TeamNotFoundError: If the team is not found

transfer_json()

Export transfer data to a JSON file.
transfers = Transfers(
    league="La Liga",
    target_season="2023-2024"
)

# Export to JSON
transfers.transfer_json(
    team="Real Madrid",
    file_name="real_madrid_transfers",
    transfer_type="both"
)

Parameters

team
str
required
Name of the team
file_name
str
required
Name of the JSON file (without .json extension)
transfer_type
Literal['in', 'out', 'both']
default:"both"
Type of transfers to export

Raises

TeamNotFoundError: If the team is not found

get_all_current_teams()

Get a list of all teams in the specified league and season.
transfers = Transfers(
    league="Premier League",
    target_season="2023-2024"
)

teams = transfers.get_all_current_teams()
print(f"Teams in Premier League 2023-2024: {len(teams)}")
for team in sorted(teams):
    print(f"  - {team}")

Returns

List[str]: List of all team names in the league for the specified season

find_team()

Find the exact team name from a partial or case-insensitive match.
transfers = Transfers(league="Bundesliga")

# Fuzzy search
team = transfers.find_team("bayern")  # Returns "Bayern Munich"
print(team)

team = transfers.find_team("dortmund")  # Returns "Borussia Dortmund"
print(team)

team = transfers.find_team("xyz")  # Returns None
print(team)

Parameters

target_team
str
required
Team name or partial identifier (case-insensitive)

Returns

str or None: Exact team name if found, None otherwise

Supported Leagues & Data Availability

Country: England
Available from: 1946-1947 season
transfers = Transfers(
    league="Premier League",
    target_season="1992-1993"  # First PL season
)

Advanced Examples

Analyze Transfer Activity

from premier_league import Transfers

transfers = Transfers(
    league="Premier League",
    target_season="2023-2024"
)

# Get all teams
teams = transfers.get_all_current_teams()

# Analyze transfer activity
transfer_stats = []

for team in teams:
    transfers_in = transfers.transfer_in_table(team)
    transfers_out = transfers.transfer_out_table(team)
    
    transfer_stats.append({
        'team': team,
        'incoming': len(transfers_in) - 1,  # Exclude header
        'outgoing': len(transfers_out) - 1,
        'net': (len(transfers_in) - 1) - (len(transfers_out) - 1)
    })

# Sort by most active
transfer_stats.sort(key=lambda x: x['incoming'] + x['outgoing'], reverse=True)

print("Most Active Transfer Teams:\n")
for stat in transfer_stats[:5]:
    print(f"{stat['team']}:")
    print(f"  In: {stat['incoming']}, Out: {stat['outgoing']}, Net: {stat['net']}")

Track Specific Position

from premier_league import Transfers

transfers = Transfers(league="Serie A")

# Find all striker signings
teams = transfers.get_all_current_teams()

striker_signings = []

for team in teams:
    transfers_in = transfers.transfer_in_table(team)
    
    for transfer in transfers_in[1:]:
        date, name, position, from_club = transfer
        if position == "FW":
            striker_signings.append({
                'player': name,
                'to': team,
                'from': from_club,
                'date': date
            })

print(f"Total striker signings in Serie A: {len(striker_signings)}\n")
for signing in striker_signings[:10]:
    print(f"{signing['player']}: {signing['from']}{signing['to']}")

Compare Seasons

from premier_league import Transfers

team_name = "Manchester United"
seasons = ["2021-2022", "2022-2023", "2023-2024"]

for season in seasons:
    transfers = Transfers(
        league="Premier League",
        target_season=season,
        cache=True
    )
    
    transfers_in = transfers.transfer_in_table(team_name)
    transfers_out = transfers.transfer_out_table(team_name)
    
    print(f"\n{team_name} - {season}:")
    print(f"  Signings: {len(transfers_in) - 1}")
    print(f"  Departures: {len(transfers_out) - 1}")
    
    if len(transfers_in) > 1:
        print("\n  Key Signings:")
        for transfer in transfers_in[1:4]:  # Top 3
            print(f"    - {transfer[1]} from {transfer[3]}")

Export League-Wide Data

from premier_league import Transfers
import os

league = "La Liga"
season = "2023-2024"

# Create output directory
output_dir = f"transfers/{league.replace(' ', '_').lower()}/{season}"
os.makedirs(output_dir, exist_ok=True)

transfers = Transfers(
    league=league,
    target_season=season
)

# Export for all teams
teams = transfers.get_all_current_teams()

for team in teams:
    safe_name = team.replace(" ", "_").replace("/", "_")
    
    # Export as CSV
    transfers.transfer_csv(
        team=team,
        file_name=f"{output_dir}/{safe_name}",
        transfer_type="both"
    )
    
    # Export as JSON
    transfers.transfer_json(
        team=team,
        file_name=f"{output_dir}/{safe_name}",
        transfer_type="both"
    )
    
    print(f"✓ Exported {team}")

print(f"\nAll transfers exported to {output_dir}/")

Identify Transfer Patterns

from premier_league import Transfers
from collections import Counter

transfers = Transfers(
    league="Premier League",
    target_season="2023-2024"
)

teams = transfers.get_all_current_teams()

# Track which leagues teams are buying from
source_leagues = []

for team in teams:
    transfers_in = transfers.transfer_in_table(team)
    
    for transfer in transfers_in[1:]:
        from_club = transfer[3]
        source_leagues.append(from_club)

# Count most common source clubs
common_sources = Counter(source_leagues).most_common(10)

print("Most Common Transfer Sources (2023-2024):\n")
for club, count in common_sources:
    print(f"{club}: {count} players")

Generate Transfer Report

from premier_league import Transfers
from datetime import datetime

def generate_transfer_report(league, season, team):
    """Generate a comprehensive transfer report"""
    
    transfers = Transfers(
        league=league,
        target_season=season
    )
    
    # Get data
    transfers_in = transfers.transfer_in_table(team)
    transfers_out = transfers.transfer_out_table(team)
    
    # Generate report
    report = []
    report.append(f"{'='*60}")
    report.append(f"TRANSFER REPORT: {team}")
    report.append(f"League: {league}")
    report.append(f"Season: {season}")
    report.append(f"Generated: {datetime.now().strftime('%Y-%m-%d %H:%M')}")
    report.append(f"{'='*60}\n")
    
    # Summary
    report.append("SUMMARY:")
    report.append(f"  Total Incoming: {len(transfers_in) - 1}")
    report.append(f"  Total Outgoing: {len(transfers_out) - 1}")
    report.append(f"  Net Transfer Activity: {(len(transfers_in) - 1) - (len(transfers_out) - 1)}\n")
    
    # Incoming
    report.append("INCOMING TRANSFERS:")
    if len(transfers_in) > 1:
        for transfer in transfers_in[1:]:
            report.append(f"  [{transfer[0]}] {transfer[1]} ({transfer[2]}) from {transfer[3]}")
    else:
        report.append("  None")
    
    report.append("\nOUTGOING TRANSFERS:")
    if len(transfers_out) > 1:
        for transfer in transfers_out[1:]:
            report.append(f"  [{transfer[0]}] {transfer[1]} ({transfer[2]}) to {transfer[3]}")
    else:
        report.append("  None")
    
    report.append(f"\n{'='*60}")
    
    # Print and save
    report_text = "\n".join(report)
    print(report_text)
    
    # Save to file
    filename = f"{team.replace(' ', '_')}_transfer_report_{season.replace('-', '_')}.txt"
    with open(filename, 'w') as f:
        f.write(report_text)
    
    print(f"\nReport saved to {filename}")

# Generate report
generate_transfer_report(
    league="Serie A",
    season="2023-2024",
    team="Napoli"
)

Find Inter-League Transfers

from premier_league import Transfers

# Track transfers between leagues
pl_transfers = Transfers(league="Premier League", target_season="2023-2024")
laliga_transfers = Transfers(league="La Liga", target_season="2023-2024")

pl_teams = pl_transfers.get_all_current_teams()
laliga_teams = laliga_transfers.get_all_current_teams()

print("Transfers from La Liga to Premier League:\n")

for pl_team in pl_teams:
    transfers_in = pl_transfers.transfer_in_table(pl_team)
    
    for transfer in transfers_in[1:]:
        date, name, position, from_club = transfer
        # Check if from_club is a La Liga team
        from_laliga = any(laliga_team.lower() in from_club.lower() for laliga_team in laliga_teams)
        
        if from_laliga:
            print(f"{name} ({position}): {from_club}{pl_team}")

Error Handling

from premier_league import Transfers, TeamNotFoundError

transfers = Transfers(
    league="Bundesliga",
    target_season="2023-2024"
)

# Handle team not found
try:
    transfers.print_transfer_table("Invalid Team Name")
except TeamNotFoundError as e:
    print(f"Error: {e}")
    print("\nAvailable teams:")
    teams = transfers.get_all_current_teams()
    for team in sorted(teams):
        print(f"  - {team}")

# Use fuzzy matching
team_search = "bayern"
matched_team = transfers.find_team(team_search)

if matched_team:
    print(f"\nFound: {matched_team}")
    transfers.print_transfer_table(matched_team)
else:
    print(f"No team found matching '{team_search}'")
Use the find_team() method for fuzzy matching when you’re unsure of the exact team name. It performs case-insensitive substring matching.
The module automatically handles multi-word club names and special formatting in transfer data, providing clean and consistent output.
Some historical seasons may have incomplete transfer data. Always verify data completeness for critical analysis.